home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dc1 / stmt.cold < prev    next >
Text File  |  1994-02-06  |  20KB  |  895 lines

  1.  
  2. /*
  3.  *  STMT.C
  4.  *
  5.  *  Parse procedural junk: declarations, statements, etc...
  6.  */
  7.  
  8. #include "defs.h"
  9.  
  10. Prototype short CompProcedureArgDeclarators(short, Var ***, long *, long *);
  11. Prototype short CompProcedure(short, Var *);
  12. Prototype short CompStmtDeclExp(short, Stmt **, long);
  13. Prototype short CompBlock(short, Stmt **);
  14. Prototype short CompFor(short, Stmt **);
  15. Prototype short CompWhile(short, Stmt **);
  16. Prototype short CompDo(short, Stmt **);
  17. Prototype short CompIf(short, Stmt **);
  18. Prototype short CompSwitch(short, Stmt **);
  19. Prototype short CompBreak(short, Stmt **);
  20. Prototype short CompContinue(short, Stmt **);
  21. Prototype short CompGoto(short, Stmt **);
  22. Prototype short CompLabel(short, Stmt **);
  23. Prototype short CompReturn(short, Stmt **);
  24. Prototype short CompBreakPoint(short, Stmt **);
  25.  
  26. /*
  27.  *  Deals with argument declarations to a procedure.  Does NOT compile
  28.  *  the procedure itself.
  29.  *
  30.  *  Determines registerization, if any, for both externs and procedure
  31.  *  definitions.
  32.  *
  33.  * void foo ( {START} a, b, c, d )   <more>
  34.  * void foo ( {START} short, short)   <more>
  35.  * void foo ( {START} short a, short b)  <more>
  36.  *
  37.  *  more =  old style declarators (which I like much better than proto style anyway),
  38.  *        optional .. could be ';' if just a prototype.  If a procedure
  39.  *        definition then returns TokSemi.
  40.  */
  41.  
  42. short
  43. CompProcedureArgDeclarators(short t, Var ***pvars, long *pargs, long *pflags)
  44. {
  45.     Var **vars = NULL;
  46.     short i;
  47.     short n = -1;
  48.     short siz = 0;
  49.     short oldState = State;
  50.  
  51.     State = SARG;
  52.  
  53.     *pargs = 0;
  54.     *pvars = NULL;
  55.     *pflags = 0;
  56.  
  57.     if (t == TokDotDotDot) {
  58.     *pflags |= TF_DOTDOTDOT | TF_PROTOTYPE;
  59.     t = GetToken();
  60.     if (t != TokRParen)
  61.         zerror(EERROR_SYNTAX_ERROR_DECL);
  62.     n = 0;
  63.     }
  64.  
  65.     while (t != TokRParen) {
  66.     Type *baseType;
  67.     Type *type;
  68.     Var *var;
  69.     Symbol *sym = NULL;
  70.     long baseFlags;
  71.     long regFlags;
  72.  
  73.     if (n < 0)
  74.         n = 0;
  75.  
  76.     /*
  77.      *  If not an ID we assume it is a type declaration and thus this
  78.      *  is a prototype.
  79.      */
  80.  
  81.     if (t != TokId && t != TokVarId && t != TokEnumConst)
  82.         *pflags |= TF_PROTOTYPE;
  83.  
  84.     t = CompType(t, &baseType, &baseFlags, ®Flags);    /*  defaults to int if none */
  85.     type = baseType;
  86.     t = CompTypeDeclarators(t, &type, &sym, baseFlags);
  87.     if (regFlags & RF_REGISTER)
  88.         *pflags |= TF_REGCALL;
  89.  
  90.     if (type == &VoidType) {
  91.         if (n)
  92.         zerror(EERROR_SYNTAX_ERROR_DECL);
  93.         if (t != TokRParen)
  94.         zerror(EERROR_SYNTAX_ERROR_DECL);
  95.         break;
  96.     }
  97.  
  98.     if (n == siz) {
  99.         siz += 4;
  100.         vars = zrealloc(vars, sizeof(Var *), n, siz);
  101.     }
  102.  
  103.     /*
  104.      *  argument
  105.      */
  106.  
  107.     var = AllocStructure(Var);
  108.     var->Type = type;
  109.     var->Sym  = sym;
  110.     var->Flags = (baseFlags & TF_STORQUALMASK) | type->Flags | (VF_ARG | TF_AUTO);
  111.     var->RegFlags = regFlags;
  112.  
  113.     if (type->Id != TID_INT && type->Id != TID_PTR && type->Id != TID_ARY)
  114.         *pflags |= TF_STKCALL;
  115.  
  116.     if (baseFlags & (TF_STATIC|TF_EXTERN))
  117.         zerror(EERROR_ILLEGAL_QUALIFIER);
  118.  
  119.     /*
  120.      *  Bump the refs for the 'register' keyword to give the variable
  121.      *  a better chance of being put in a register.
  122.      */
  123.  
  124.     if (var->Flags & TF_REGISTER)
  125.         ++var->Refs;
  126.  
  127.     vars[n++] = var;
  128.  
  129.     if (t != TokRParen && t != TokComma) {
  130.         zerror(EERROR_SYNTAX_ERROR_DECL);
  131.         goto bad;
  132.     }
  133.     if (t == TokComma) {
  134.         t = GetToken();
  135.         if (t == TokDotDotDot) {
  136.         *pflags |= TF_DOTDOTDOT;
  137.         t = GetToken();
  138.         if (t != TokRParen)
  139.             zerror(EERROR_SYNTAX_ERROR_DECL);
  140.         }
  141.     }
  142.     }
  143.     *pargs = n;
  144.     *pvars = vars;
  145.  
  146.     /*
  147.      *    have right paren, now is this a real procedure or just a declaration
  148.      *    of some sort?
  149.      */
  150.  
  151.     t = GetToken();
  152.  
  153.     if (t == TokComma || t == TokEq || t == TokSemi || t == TokRParen) {
  154.     if (!(*pflags & TF_PROTOTYPE))
  155.         *pflags |= TF_STKCALL;
  156.     goto skip;
  157.     }
  158.  
  159.     /*
  160.      *    Else a real procedure.. handle old-style argument decls.  We return
  161.      *    when we get a '{'.  Also make sure all the variables are named.
  162.      */
  163.  
  164.     for (i = 0; i < n; ++i) {
  165.     Var *var = vars[i];
  166.  
  167.     if (var->Sym == NULL) {
  168.         zerror(EERROR_ID_MISSING_PROC);
  169.         var->Sym = MakeSymbol("____dummy", 9, TokId, 0);
  170.         /* goto bad; */
  171.         /* break; */
  172.     }
  173.     }
  174.  
  175.     while (t != TokLBrace) {
  176.     Type *baseType;
  177.     Type *type;
  178.     Var *var;
  179.     Symbol *sym = NULL;    /*  XXX needed? */
  180.     long  baseFlags;
  181.     long  regFlags;
  182.     long  li = LFBase->lf_Index;
  183.  
  184.     t = CompType(t, &baseType, &baseFlags, ®Flags);     /*  defaults to int if none */
  185.  
  186.     for (;;) {
  187.         type = baseType;
  188.         t = CompTypeDeclarators(t, &type, &sym, baseFlags);
  189.  
  190.         for (i = 0; i < n; ++i) {
  191.         var = vars[i];
  192.         if (var->Sym == sym)
  193.             break;
  194.         }
  195.         if (i == n) {
  196.         zerror(EERROR_ID_NOT_IN_LIST);
  197.         } else {
  198.         var->Type = type;
  199.         var->Flags = (baseFlags & TF_STORQUALMASK) | type->Flags | (VF_ARG | TF_AUTO);
  200.         var->RegFlags = regFlags;
  201.         if (var->Flags & TF_REGISTER)
  202.             ++var->Refs;
  203.         if (regFlags & RF_REGISTER)
  204.             *pflags |= TF_REGCALL;
  205.         }
  206.         if (type->Id != TID_INT && type->Id != TID_PTR && type->Id != TID_ARY)
  207.         *pflags |= TF_STKCALL;
  208.  
  209.         if (t == TokComma) {
  210.         t = GetToken();
  211.         continue;
  212.         }
  213.         break;
  214.     }
  215.     if (t != TokSemi) {
  216.         zerror(EERROR_EXPECTED_SEMICOLON);
  217.         if (li == LFBase->lf_Index)     /*    prevent inifinite loop    */
  218.         t = GetToken();
  219.         break;
  220.     }
  221.     t = GetToken();
  222.     }
  223.  
  224. skip:
  225.  
  226.     /*
  227.      *    If explicitly registerized then clear TF_STKCALL bit (which gets
  228.      *    set when automatic registerization is not possible)
  229.      */
  230.  
  231.     if (*pflags & TF_REGCALL)
  232.     *pflags &= ~TF_STKCALL;
  233.  
  234. bad:
  235.     State = oldState;
  236.     return(t);
  237. }
  238.  
  239. /*
  240.  *  Compiles a procedure, t had better be TokLBrace.
  241.  *
  242.  *  returns TokSemi to simply toplevel.c
  243.  *
  244.  *  Normally assigns in decls work as follows:    the variable is added to the
  245.  *  current block's variable list and the decl-stmt is added to the current
  246.  *  block's statement list (which retains placement).
  247.  */
  248.  
  249. short
  250. CompProcedure(short t, Var *var)
  251. {
  252.     Stmt *stmt;
  253.     short oldState = State;
  254.     long lexIdx = LFBase->lf_Index;
  255.  
  256.     if (t != TokLBrace)
  257.     zerror(EERROR_EXPECTED_OCBRACE_PROC);
  258.  
  259.     State = SARG;        /*    first properly add args */
  260.     var->u.Block = BlockDown(BT_PROC);
  261.  
  262.     {
  263.     short i;
  264.     Type *type = var->Type;
  265.  
  266.     for (i = 0; i < type->Args; ++i) {
  267.         Var *xvar = type->Vars[i];
  268.  
  269.         BlockAddVar(xvar);
  270.         Assert(xvar->Sym);
  271.         SemanticAdd(xvar->Sym, TokVarId, xvar);
  272.     }
  273.     }
  274.  
  275.     State = SINSIDE;
  276.     t = CompBlock(GetToken(), &stmt);
  277.     BlockAddStmt(stmt);
  278.  
  279.     State = SARG;
  280.     BlockUp();
  281.     State = SOUTSIDE;
  282.  
  283.     /*
  284.      *    t should be TokRBrace.. return TokSemi instead
  285.      */
  286.  
  287.     if (t != TokRBrace)
  288.     yerror(lexIdx, EERROR_EXPECTED_OCBRACE_PROC);
  289.  
  290.     State = oldState;
  291.     return(TokSemi);
  292. }
  293.  
  294. short
  295. CompStmtDeclExp(short t, Stmt **pstmt, long semiexp)
  296. {
  297.     *pstmt = NULL;
  298.  
  299.     switch(t) {
  300.     case TokLBrace:
  301.     t = CompBlock(GetToken(), pstmt);
  302.     t = GetToken();
  303.     break;
  304.     case TokBreak:
  305.     t = CompBreak(GetToken(), pstmt);
  306.     break;
  307.     case TokCase:
  308.     zerror(EERROR_CASE_DEFAULT_OUTSIDE);
  309.     t = GetToken();
  310.     break;
  311.     case TokContinue:
  312.     t = CompContinue(GetToken(), pstmt);
  313.     break;
  314.     case TokDefault:
  315.     zerror(EERROR_CASE_DEFAULT_OUTSIDE);
  316.     t = GetToken();
  317.     break;
  318.     case TokDo:
  319.     BlockCost += 2;
  320.     t = CompDo(GetToken(), pstmt);
  321.     BlockCost -= 2;
  322.     break;
  323.     case TokElse:
  324.     zerror(EERROR_ELSE_NO_IF);
  325.     t = GetToken();
  326.     break;
  327.     case TokFor:
  328.     BlockCost += 2;
  329.     t = CompFor(GetToken(), pstmt);
  330.     BlockCost -= 2;
  331.     break;
  332.     case TokGoto:
  333.     t = CompGoto(GetToken(), pstmt);
  334.     break;
  335.     case TokIf:
  336.     t = CompIf(GetToken(), pstmt);
  337.     break;
  338.     case TokReturn:
  339.     t = CompReturn(GetToken(), pstmt);
  340.     break;
  341.     case TokSwitch:
  342.     t = CompSwitch(GetToken(), pstmt);
  343.     break;
  344.     case TokWhile:
  345.     BlockCost += 2;
  346.     t = CompWhile(GetToken(), pstmt);
  347.     BlockCost -= 2;
  348.     break;
  349.     case TokBreakPoint:
  350.     t = CompBreakPoint(GetToken(), pstmt);
  351.     break;
  352.     case TokSemi:
  353.     if (semiexp)
  354.         t = GetToken();
  355.     break;
  356.  
  357.     /*
  358.      *    declaration
  359.      */
  360.  
  361.     case TokStruct:
  362.     case TokEnum:
  363.     case TokUnion:
  364.     case TokTypeQual:
  365.     case TokTypeDef:
  366.     case TokTypeId:
  367.     case TokTypeof:
  368.     {
  369.         Var *var = NULL;
  370.         BlockStmt *block = NULL;
  371.  
  372.         t = CompDecl(t, &var, semiexp);
  373.  
  374.         /*
  375.          *    add variables to the current block, any procedure decls
  376.          *    will be moved to the top level.  Returns base of list
  377.          *    of newly added variables to the current block (minus any
  378.          *    procdures added to the top)
  379.          */
  380.  
  381.         if (var)
  382.         var = BlockAddVar(var);
  383.  
  384.         if (var && var->Next)           /*  more 'n one!    */
  385.         block = BlockDown(BT_BLOCK);
  386.  
  387.         while (var) {        /*  for each...     */
  388.         if (var->Type->Id != TID_PROC && var->u.AssExp && (var->Flags & TF_AUTO)) {
  389.             ExpStmt *es = AllocTmpStructure(ExpStmt);
  390.  
  391.             /*
  392.             if (var->u.AssExp->ex_Token == TokExpAssBlock)
  393.             cerror(ESOFT, "DICE cannot handle local braced assignments yet");
  394.             */
  395.  
  396.             es->st_Func = (void (*)(void *))GenExp;
  397.             es->st_Tok    = TokExp;
  398.             es->st_LexIdx = LFBase->lf_Index;
  399.             InsertAssign(&var->u.AssExp, var);
  400.             es->Expr = var->u.AssExp;
  401.             ++var->Refs;
  402.             if (block)
  403.             BlockAddStmt((Stmt *)es);
  404.             else
  405.             *pstmt = (Stmt *)es;
  406.         }
  407.         var = var->Next;
  408.         }
  409.         if (block) {
  410.         *pstmt = (Stmt *)block;
  411.         BlockUp();
  412.         }
  413.     }
  414.     break;
  415.     case TokLabelId:
  416.     Assert(0);
  417.     /* t = CompLabel(t, pstmt); */
  418.     break;
  419.     case TokId:     /*    label or subroutine call ?    */
  420.     case TokVarId:  /*    label or variable ?          */
  421.     if (LexHackColon) {    /*  label (lexical hack checks for a :) */
  422.         t = CompLabel(t, pstmt);
  423.         break;
  424.     }
  425.     /* fall through to exp */
  426.     default:
  427.  
  428.     {
  429.         Exp *exp = NULL;
  430.         ExpStmt *es = AllocTmpStructure(ExpStmt);
  431.         long li = LFBase->lf_Index;
  432.  
  433.         t = CompExp(t, &exp, 1);
  434.         if (semiexp) {
  435.         if (t == TokSemi) {
  436.             t = GetToken();
  437.         } else {
  438.             zerror(EWARN_EXPECTED_SEMICOLON);
  439.             if (LFBase->lf_Index = li)     /*  prevent endless loop */
  440.             t = GetToken();
  441.         }
  442.         }
  443.         if (exp == NULL)
  444.         zerror(EFATAL_SYNTAX_ERROR_EXP);
  445.  
  446.         es->st_Func = (void (*)(void *))GenExp;
  447.         es->st_Tok    = TokExp;
  448.         es->st_LexIdx = exp->ex_LexIdx;
  449.         es->Expr = exp;
  450.         *pstmt = (Stmt *)es;
  451.     }
  452.     break;
  453.     }
  454.     return(t);
  455. }
  456.  
  457. /*
  458.  *  CompBlock() works slightly differently in that it returns t = TokRBrace,
  459.  *  allowing toplevel.c to simply throw away t (makes the code easier)
  460.  *
  461.  *  All Comp*() for statements have access to their parent blocks... they
  462.  *  need not set it (it's done automatically on return) UNLESS they make
  463.  *  calls to other Comp*() statements.
  464.  *
  465.  *  Attempt to set block->LastLexIdx for debug info synchronization to just
  466.  *  before the close brace.  This does not always work perfectly (but does
  467.  *  not cause a screwup in those cases either).
  468.  */
  469.  
  470. short
  471. CompBlock(short t, Stmt **pstmt)
  472. {
  473.     BlockStmt *block = BlockDown(BT_BLOCK);
  474.  
  475.     *pstmt = (Stmt *)block;
  476.  
  477.     while (t != TokRBrace) {
  478.     Stmt *stmt;
  479.  
  480.     t = CompStmtDeclExp(t, &stmt, 1);
  481.     BlockAddStmt(stmt);
  482.     if (!t)
  483.         break;
  484.     }
  485.     BlockUp();
  486.  
  487.     return(t);
  488. }
  489.  
  490. /*
  491.  *  for (stmt ; exp; stmt) stmt
  492.  *
  493.  *  Note: The Block junk is to add another variable level allowing
  494.  *  temporary declarations within the for.. for (int i = 0; ...)
  495.  */
  496.  
  497. short
  498. CompFor(short t, Stmt **pstmt)
  499. {
  500.     ForStmt *stmt = AllocTmpStructure(ForStmt);
  501.     BlockStmt *block = BlockDown(BT_FOR);
  502.  
  503.     *pstmt = (Stmt *)block;
  504.     stmt->Block = block;
  505.     block->LabelLoop  = AllocLabel();
  506.     block->LabelTest  = AllocLabel();
  507.     block->LabelBreak = AllocLabel();
  508.  
  509.  
  510.     BlockAddStmt((Stmt *)stmt);
  511.  
  512.     stmt->st_Func = (void (*)(void *))GenFor;
  513.     stmt->st_Tok  = TokFor;
  514.     stmt->st_LexIdx = LFBase->lf_Index;
  515.     stmt->LabelBegin = AllocLabel();
  516.  
  517.     t = SkipToken(t, TokLParen);
  518.  
  519.     if (t != TokSemi)
  520.     t = CompStmtDeclExp(t, &stmt->Stmt1, 0);
  521.     t = SkipToken(t, TokSemi);
  522.     if (t != TokSemi)
  523.     t = CompStmtDeclExp(t, &stmt->Stmt2, 0);
  524.     t = SkipToken(t, TokSemi);
  525.     if (t != TokRParen)
  526.     t = CompStmtDeclExp(t, &stmt->Stmt3, 0);
  527.     t = SkipToken(t, TokRParen);
  528.     t = CompStmtDeclExp(t, &stmt->Stmt4, 1);
  529.  
  530.     if (stmt->Stmt2) {
  531.     if (stmt->Stmt2->st_Tok != TokExp)
  532.         zerror(EFATAL_STMT_COND_NOT_EXP);
  533.  
  534.     InsertBranch(&((ExpStmt *)stmt->Stmt2)->Expr, COND_T, block->LabelLoop);
  535.     }
  536.  
  537.     BlockUp();
  538.  
  539.     return(t);
  540. }
  541.  
  542. short
  543. CompWhile(short t, Stmt **pstmt)
  544. {
  545.     WhileStmt *stmt = AllocTmpStructure(WhileStmt);
  546.     BlockStmt *block = BlockDown(BT_WHILE);
  547.  
  548.     *pstmt = (Stmt *)block;
  549.     stmt->Block = block;
  550.     block->LabelLoop  = AllocLabel();
  551.     block->LabelTest  = AllocLabel();
  552.     block->LabelBreak = AllocLabel();
  553.  
  554.     BlockAddStmt((Stmt *)stmt);
  555.  
  556.     stmt->st_Func = (void (*)(void *))GenWhile;
  557.     stmt->st_Tok  = TokWhile;
  558.     stmt->st_LexIdx = LFBase->lf_Index;
  559.  
  560.     t = SkipToken(t, TokLParen);
  561.  
  562.     t = CompStmtDeclExp(t, &stmt->Stmt1, 0);
  563.     t = SkipToken(t, TokRParen);
  564.     t = CompStmtDeclExp(t, &stmt->Stmt2, 1);
  565.  
  566.     if (stmt->Stmt1->st_Tok != TokExp)
  567.     zerror(EFATAL_STMT_COND_NOT_EXP);
  568.     InsertBranch(&((ExpStmt *)stmt->Stmt1)->Expr, COND_T, block->LabelLoop);
  569.  
  570.     BlockUp();
  571.  
  572.     return(t);
  573. }
  574.  
  575. short
  576. CompDo(short t, Stmt **pstmt)
  577. {
  578.     DoStmt *stmt = AllocTmpStructure(DoStmt);
  579.     BlockStmt *block = BlockDown(BT_DO);
  580.  
  581.     *pstmt = (Stmt *)block;
  582.     stmt->Block = block;
  583.     block->LabelLoop  = AllocLabel();
  584.     block->LabelTest  = AllocLabel();
  585.     block->LabelBreak = AllocLabel();
  586.  
  587.     BlockAddStmt((Stmt *)stmt);
  588.  
  589.     stmt->st_Func = (void (*)(void *))GenDo;
  590.     stmt->st_Tok  = TokDo;
  591.     stmt->st_LexIdx = LFBase->lf_Index;
  592.  
  593.     t = CompStmtDeclExp(t, &stmt->Stmt1, 1);      /*  code    */
  594.     t = SkipToken(t, TokWhile);
  595.     t = CompStmtDeclExp(t, &stmt->Stmt2, 1);      /*  test    */
  596.  
  597.     if (stmt->Stmt2->st_Tok != TokExp)
  598.     zerror(EFATAL_STMT_COND_NOT_EXP);
  599.     InsertBranch(&((ExpStmt *)stmt->Stmt2)->Expr, COND_T, block->LabelLoop);
  600.  
  601.     BlockUp();
  602.  
  603.     return(t);
  604. }
  605.  
  606. short
  607. CompIf(short t, Stmt **pstmt)
  608. {
  609.     IfStmt *stmt = AllocTmpStructure(IfStmt);
  610.  
  611.     *pstmt = (Stmt *)stmt;
  612.     stmt->st_Func = (void (*)(void *))GenIf;
  613.     stmt->st_Tok  = TokIf;
  614.     stmt->st_LexIdx = LFBase->lf_Index;
  615.  
  616.     stmt->LabelIf   = AllocLabel();
  617.     stmt->LabelElse = AllocLabel();
  618.     stmt->LabelEnd  = AllocLabel();
  619.  
  620.     t = SkipToken(t, TokLParen);
  621.     t = CompStmtDeclExp(t, &stmt->Stmt1, 0);      /*  cond    */
  622.     t = SkipToken(t, TokRParen);
  623.     t = CompStmtDeclExp(t, &stmt->StmtT, 1);      /*  true    */
  624.     if (t == TokElse)
  625.     t = CompStmtDeclExp(GetToken(), &stmt->StmtF, 1); /*  false */
  626.  
  627.     if (stmt->Stmt1->st_Tok != TokExp)
  628.     zerror(EFATAL_STMT_COND_NOT_EXP);
  629.     InsertBranch(&((ExpStmt *)stmt->Stmt1)->Expr, COND_F, stmt->LabelElse);
  630.  
  631.     return(t);
  632. }
  633.  
  634. /*
  635.  *  switch (exp) { ... }
  636.  *
  637.  *  Not only is exp in a semantic level, but each case/default is as well, so
  638.  *  you can:        case 1:
  639.  *            int i = 4;
  640.  *            ...
  641.  *            case 2:
  642.  *            int i = 5;
  643.  *            ...
  644.  *
  645.  */
  646.  
  647. short
  648. CompSwitch(short t, Stmt **pstmt)
  649. {
  650.     SwitchStmt *stmt = AllocTmpStructure(SwitchStmt);
  651.     BlockStmt *block = BlockDown(BT_SWITCH);
  652.     short siz = 0;
  653.     short haveCase = 0;
  654.  
  655.     *pstmt = (Stmt *)block;
  656.  
  657.     BlockAddStmt((Stmt *)stmt);
  658.  
  659.     stmt->st_Func = (void (*)(void *))GenSwitch;
  660.     stmt->st_Tok  = TokSwitch;
  661.     stmt->st_LexIdx = LFBase->lf_Index;
  662.  
  663.     stmt->Block = block;
  664.  
  665.     block->LabelLoop  = AllocLabel();
  666.     block->LabelBreak = AllocLabel();
  667.  
  668.     t = SkipToken(t, TokLParen);
  669.     t = CompStmtDeclExp(t, &stmt->Stmt1, 0);    /*  exp  */
  670.     Assert(stmt->Stmt1->st_Tok == TokExp);
  671.                         /*    don't deallocate result!  */
  672.     stmt->Stmt1->st_Func = (void (*)(void *))GenExpResult;
  673.  
  674.     t = SkipToken(t, TokRParen);
  675.     t = SkipToken(t, TokLBrace);
  676.  
  677.     /*
  678.      *    now, each case and default is in its own block.
  679.      */
  680.  
  681.     while (t && t != TokRBrace) {
  682.     if (t == TokCase) {
  683.         Exp *exp;
  684.  
  685.         if (siz == stmt->NumCases) {
  686.         if (siz >= 32)
  687.             siz *= 2;
  688.         else
  689.             siz += 4;
  690.         stmt->Cases = zrealloc(stmt->Cases, sizeof(stmt->Cases[0]), stmt->NumCases, siz);
  691.         stmt->Labels= zrealloc(stmt->Labels, sizeof(stmt->Labels[0]), stmt->NumCases, siz);
  692.         stmt->CaseAry = zrealloc(stmt->CaseAry, sizeof(stmt->CaseAry[0]), stmt->NumCases, siz);
  693.         }
  694.  
  695.         if (haveCase)
  696.         BlockUp();
  697.         stmt->CaseAry[stmt->NumCases] = BlockDown(BT_BLOCK);
  698.         {
  699.         long l = AllocLabel();
  700.  
  701.         stmt->CaseAry[stmt->NumCases]->LabelTest = l;
  702.         stmt->Labels[stmt->NumCases] = l;
  703.         }
  704.         t = CompExp(GetToken(), &exp, 1);
  705.         stmt->Cases[stmt->NumCases] = ExpToConstant(exp);
  706.         ++stmt->NumCases;
  707.         t = SkipToken(t, TokColon);
  708.         haveCase = 1;
  709.     } else if (t == TokDefault) {
  710.         if (haveCase)
  711.         BlockUp();
  712.         if (stmt->DefBlock)
  713.         zerror(EERROR_DUPLICATE_DEFAULT);
  714.         stmt->DefBlock = BlockDown(BT_BLOCK);
  715.         stmt->DefBlock->LabelTest = AllocLabel();
  716.         stmt->DefCaseNo = stmt->NumCases;    /*  insert before...    */
  717.  
  718.         t = SkipToken(GetToken(), TokColon);
  719.         haveCase = 1;
  720.     } else {
  721.         Stmt *caseStmt;
  722.  
  723.         t = CompStmtDeclExp(t, &caseStmt, 1);
  724.         BlockAddStmt(caseStmt);
  725.         if (haveCase == 0 && caseStmt) {
  726.         if (caseStmt->Hdr.Tok != TokBlock || ((BlockStmt *)caseStmt)->Base)
  727.             zerror(EERROR_STATEMENTS_BEFORE_CASE);
  728.         }
  729.     }
  730.     }
  731.  
  732.     if (haveCase)
  733.     BlockUp();
  734.  
  735.     t = GetToken();
  736.  
  737.     BlockUp();
  738.  
  739.     return(t);
  740. }
  741.  
  742. /*
  743.  *  break;
  744.  */
  745.  
  746. short
  747. CompBreak(short t, Stmt **pstmt)
  748. {
  749.     BreakStmt *stmt = AllocTmpStructure(BreakStmt);
  750.  
  751.     t = SkipToken(t, TokSemi);
  752.  
  753.     *pstmt = (Stmt *)stmt;
  754.     stmt->st_Func = (void (*)(void *))GenBreak;
  755.     stmt->st_Tok  = TokBreak;
  756.     stmt->st_LexIdx = LFBase->lf_Index;
  757.     if ((stmt->BreakLabel = FindBreakLabel()) == 0)
  758.     zerror(EERROR_BREAK_OUTSIDE_LOOPSW);
  759.     return(t);
  760. }
  761.  
  762. short
  763. CompContinue(short t, Stmt **pstmt)
  764. {
  765.     ContinueStmt *stmt = AllocTmpStructure(ContinueStmt);
  766.  
  767.     t = SkipToken(t, TokSemi);
  768.  
  769.     *pstmt = (Stmt *)stmt;
  770.     stmt->st_Func = (void (*)(void *))GenContinue;
  771.     stmt->st_Tok  = TokContinue;
  772.     stmt->st_LexIdx = LFBase->lf_Index;
  773.     if ((stmt->ContLabel = FindContinueLabel()) == 0)
  774.     zerror(EERROR_CONT_OUTSIDE_LOOP);
  775.     return(t);
  776. }
  777.  
  778. /*
  779.  *  goto label;
  780.  */
  781.  
  782. short
  783. CompGoto(short t, Stmt **pstmt)
  784. {
  785.     GotoStmt *stmt = AllocTmpStructure(GotoStmt);
  786.     SemInfo *sem;
  787.     long label;
  788.  
  789.     *pstmt = (Stmt *)stmt;
  790.     stmt->st_Func = (void (*)(void *))GenGoto;
  791.     stmt->st_Tok  = TokGoto;
  792.     stmt->st_LexIdx = LFBase->lf_Index;
  793.  
  794.     switch(t) {
  795.     case TokId:
  796.     case TokVarId:
  797.     case TokEnumConst:
  798.     if ((sem = FindSymbolId(LexSym, TokLabelId)) == NULL) {
  799.         label = AllocLabel();
  800.         SemanticAddTopBlock(LexSym, TokLabelId, (void *)label);
  801.         break;
  802.     }
  803.     label = (long)sem->Data;
  804.     break;
  805.     case TokLabelId:
  806.     Assert(0);
  807.     /* label = (long)LexData; */
  808.     break;
  809.     default:
  810.     zerror(EERROR_SYNTAX_ERROR_EXP);
  811.     break;
  812.     }
  813.     stmt->GotoLabel = label;
  814.     t = GetToken();
  815.     t = SkipToken(t, TokSemi);
  816.     return(t);
  817. }
  818.  
  819. short
  820. CompLabel(short t, Stmt **pstmt)
  821. {
  822.     LabelStmt *stmt = AllocTmpStructure(LabelStmt);
  823.     SemInfo *sem;
  824.     long label;
  825.  
  826.     *pstmt = (Stmt *)stmt;
  827.     stmt->st_Func = (void (*)(void *))GenLabel;
  828.     stmt->st_Tok  = TokLabelId;
  829.     stmt->st_LexIdx = LFBase->lf_Index;
  830.  
  831.     if ((sem = FindSymbolId(LexSym, TokLabelId)) == NULL) {
  832.     label = AllocLabel();
  833.     SemanticAddTopBlock(LexSym, TokLabelId, (void *)label);
  834.     } else {
  835.     label = (long)sem->Data;
  836.     }
  837.     stmt->Label = label;
  838.     t = SkipToken(GetToken(), TokColon);
  839.  
  840.     /*
  841.      *    normally label: is bundled with a statement.  However, there are
  842.      *    a few special cases where this is not so.
  843.      */
  844.  
  845.     if (t != TokRBrace && t != TokCase && t != TokDefault)
  846.     t = CompStmtDeclExp(t, &stmt->Stmt1, 1);
  847.     return(t);
  848. }
  849.  
  850.  
  851. /*
  852.  *  return exp;
  853.  */
  854.  
  855. short
  856. CompReturn(short t, Stmt **pstmt)
  857. {
  858.     ReturnStmt *stmt = AllocTmpStructure(ReturnStmt);
  859.  
  860.     *pstmt = (Stmt *)stmt;
  861.     stmt->st_Func = (void (*)(void *))GenReturn;
  862.     stmt->st_Tok  = TokReturn;
  863.     stmt->st_LexIdx = LFBase->lf_Index;
  864.  
  865.     if (t != TokSemi) {
  866.     t = CompStmtDeclExp(t, &stmt->Stmt1, 0);    /*    exp  */
  867.     if (stmt->Stmt1->st_Tok != TokExp)
  868.         zerror(EFATAL_SYNTAX_ERROR_EXP);
  869.                             /*    save result */
  870.     stmt->Stmt1->st_Func = (void (*)(void *))GenExpResult;
  871.     }
  872.     t = SkipToken(t, TokSemi);
  873.  
  874.     return(t);
  875. }
  876.  
  877. /*
  878.  *  __breakpoint
  879.  */
  880.  
  881. short
  882. CompBreakPoint(short t, Stmt **pstmt)
  883. {
  884.     BreakPointStmt *stmt = AllocTmpStructure(BreakPointStmt);
  885.  
  886.     *pstmt = (Stmt *)stmt;
  887.     stmt->st_Func = (void (*)(void *))GenBreakPoint;
  888.     stmt->st_Tok  = TokBreakPoint;
  889.     stmt->st_LexIdx = LFBase->lf_Index;
  890.  
  891.     return(t);
  892. }
  893.  
  894.  
  895.